package com.alinesno.cloud.common.web.login.shiro;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

import com.alinesno.cloud.base.boot.feign.dto.ManagerAccountDto;
import com.alinesno.cloud.base.boot.feign.facade.ManagerAccountFeigin;
import com.alinesno.cloud.common.web.base.utils.ManagerSettingsUtils;
import com.alinesno.cloud.common.web.login.constants.LoginConstants;
import com.alinesno.cloud.common.web.login.token.LoginAccountToken;

import io.micrometer.core.instrument.util.StringUtils;

/**
 * 用户认证信息
 * 
 * @author LuoAnDong
 * @sine 2019年4月5日 上午10:55:44
 */
@Component
public class AccountRealm extends AuthorizingRealm {

	private static final Logger log = LoggerFactory.getLogger(AccountRealm.class);

	@Autowired
	private ManagerAccountFeigin managerAccountFeigin;

	/**
	 * 获取授权信息
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		String username = (String) principals.getPrimaryPrincipal();

		log.debug("[{}]权限认证.", username);
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

		return info;
	}

	/**
	 * 登录认证
	 */
	@DependsOn("managerAccountFeigin")
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
			throws AuthenticationException {
		LoginAccountToken token = (LoginAccountToken) authenticationToken;
		log.debug("[{}]身份认证方法.", ToStringBuilder.reflectionToString(token));

		// 从数据库获取对应用户名密码的用户
		ManagerAccountDto dto = managerAccountFeigin.findByLoginName(token.getUsername());
		log.debug("maanger account dto: {}", ToStringBuilder.reflectionToString(dto));
		
		// 验证码
		validateCaptcha(token) ;

		if (null == dto) {
			throw new UnknownAccountException("用户名不正确");
		} else if (!dto.getPassword().equals(new String((char[]) token.getCredentials()))) {
			throw new IncorrectCredentialsException("密码不正确");
		}

		String password = dto.getPassword();

		// 设置Session
		Subject subject = SecurityUtils.getSubject();
		dto.setPassword(""); // 清理密码
		subject.getSession().setAttribute(LoginConstants.CURRENT_USER, dto);

		return new SimpleAuthenticationInfo(token.getPrincipal(), password, getName());
	}

	/**
	 * 验证码校验
	 * 
	 * @return
	 */
	private boolean validateCaptcha(LoginAccountToken token) {

		boolean b = ManagerSettingsUtils.isOpenCaptcha(); // 验证是否需要打开
		if (b) {
			Object captcha = SecurityUtils.getSubject().getSession().getAttribute(LoginConstants.VERIFY_CODE_ACTUAL) ;
			String pageCaptcha = token.getCaptcha();
			
			if (captcha == null || pageCaptcha == null || StringUtils.isBlank(pageCaptcha)) {
				throw new IncorrectCredentialsException("验证码为空.");
			} 
			
			if(captcha.equals(pageCaptcha)) {
				return true ; 
			}else {
				throw new IncorrectCredentialsException("验证码不正确");
			}
			
		} 

		return true ;
	}

}
